<?php

// 应用公共文件
use think\facade\Cache;
use think\facade\Config;
use think\facade\Db;
use think\facade\Request;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use RongCloud\RongCloud;
use dh2y\qrcode\QRcode;
//设置缓存
function set_cache($key, $value, $date = 86400)
{
    Cache::set($key, $value, $date);
}

//读取缓存
function get_cache($key)
{
    return Cache::get($key);
}

//清空缓存
function clear_cache($key)
{
    Cache::clear($key);
}


//读取文件配置
function get_config($key)
{
    return Config::get($key);
}

//读取系统配置
function get_system_config($name,$key='')
{
    $config=[];
    if (get_cache('system_config' . $name)) {
        $config = get_cache('system_config' . $name);
    } else {
        $conf = Db::name('config')->where('name',$name)->find();
        if($conf['content']){
            $config = unserialize($conf['content']);
        }
        set_cache('system_config' . $name, $config);
    }
    if($key==''){
        return $config;
    }
    else{
        if($config[$key]){
            return $config[$key];
        }
    }
}

//系统信息
function get_system_info($key)
{
    $system = [
        'os' => PHP_OS,
        'php' => PHP_VERSION,
        'upload_max_filesize' => get_cfg_var("upload_max_filesize") ? get_cfg_var("upload_max_filesize") : "不允许上传附件",
        'max_execution_time' => get_cfg_var("max_execution_time") . "秒 ",
    ];
    if (empty($key)) {
        return $system;
    } else {
        return $system[$key];
    }
}

//获取url参数
function get_params($key = "")
{
    return Request::instance()->param($key);
}

//生成一个不会重复的字符串
function make_token()
{
    $str = md5(uniqid(md5(microtime(true)), true));
    $str = sha1($str); //加密
    return $str;
}

//随机字符串，默认长度10
function set_salt($num = 10)
{
    $str = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890';
    $salt = substr(str_shuffle($str), 10, $num);
    return $salt;
}
//密码加密
function set_password($pwd, $salt)
{
    return md5(md5($pwd . $salt) . $salt);
}

//判断cms是否完成安装
function is_installed()
{
    static $isInstalled;
    if (empty($isInstalled)) {
        $isInstalled = file_exists(CMS_ROOT . 'config/install.lock');
    }
    return $isInstalled;
}

//判断cms是否存在模板
function isTemplate($url='')
{
    static $isTemplate;
    if (empty($isTemplate)) {
        $isTemplate = file_exists(CMS_ROOT . 'app/'.$url);
    }
    return $isTemplate;
}


//递归返回树形菜单数据
function get_tree($data, $pId ,$open=0,$deep=0)
{
    $tree = [];
    foreach($data as $k => $v)
    {
        $v['checkArr']=array('type'=>0, 'isChecked'=>0);
        $v['spread']=true;
        $v['parentId']=$v['pid'];
        if($deep>=$open){
            $v['spread']=true;
        }
        $v['name']=$v['title'];
        if($v['pid'] == $pId){
            //父亲找到儿子
            $deep++;
            $v['children'] = get_tree($data, $v['id'],$open,$deep);
            $tree[] = $v;
        }
    }
    return array_values($tree);
}

/**
 * PHP截取文字长度
 * @return string
 */
function sub_str($str,$len=2){
    $strlen=strlen($str)/3;#在编码utf8下计算字符串的长度，并把它交给变量$strlen
    #echo $strlen;#输出字符串长度
    if($strlen<$len){
        return $str;
    }else{
        return mb_substr($str,0,$len,"utf-8")."...";
    }
}

/**
 * <br />转/n
 * @return string
 */
function br2nl($text){
    return preg_replace('/<br\\s*?\/??>/i','',$text);
}


/**
 * 返回json数据，用于接口
 * @param    integer    $code
 * @param    string     $msg
 * @param    array      $data
 * @param    string     $url
 * @param    integer    $httpCode
 * @param    array      $header
 * @param    array      $options
 * @return   json
 */
function to_assign($code = 0, $msg = "操作成功", $data = [], $url = '', $httpCode = 200, $header = [], $options = [])
{
    $res = ['code' => $code];
    $res['msg'] = $msg;
    $res['url'] = $url;
    if (is_object($data)) {
        $data = $data->toArray();
    }
    $res['data'] = $data;
    $response = \think\Response::create($res, "json", $httpCode, $header, $options);
    throw new \think\exception\HttpResponseException($response);
}

/**
 * 适配layui数据列表的返回数据方法，用于接口
 * @param    integer    $code
 * @param    string     $msg
 * @param    array      $data
 * @param    integer    $httpCode
 * @param    array      $header
 * @param    array      $options
 * @return   json
 */
function table_assign($code = 0, $msg = '请求成功', $data = [], $httpCode = 200, $header = [], $options = [])
{
    $res['code'] = $code;
    $res['msg'] = $msg;
    if (is_object($data)) {
        $data = $data->toArray();
    }
    if (!empty($data['total'])) {
        $res['count'] = $data['total'];
    } else {
        $res['count'] = 0;
    }
    $res['data'] = $data['data'];
    $response = \think\Response::create($res, "json", $httpCode, $header, $options);
    throw new \think\exception\HttpResponseException($response);
}

//菜单转为父子菜单
function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = 'list', $root = 0)
{
    // 创建Tree
    $tree = array();
    if (is_array($list)) {
        // 创建基于主键的数组引用
        $refer = array();
        foreach ($list as $key => $data) {
            $refer[$data[$pk]] = &$list[$key];
        }
        foreach ($list as $key => $data) {
            // 判断是否存在parent
            $parentId = $data[$pid];
            if ($root == $parentId) {
                $tree[$data[$pk]] = &$list[$key];
            } else {
                if (isset($refer[$parentId])) {
                    $parent = &$refer[$parentId];
                    $parent[$child][$data[$pk]] = &$list[$key];
                }
            }
        }
    }
    return $tree;
}
/**
 * 时间戳格式化
 * @param int    $time
 * @param string $format 默认'Y-m-d H:i'，x代表毫秒
 * @return string 完整的时间显示
 */
function time_format($time = NULL, $format = 'Y-m-d H:i:s')
{
    $usec = $time = $time === null ? '' : $time;
    if (strpos($time, '.')!==false) {
        list($usec, $sec) = explode(".", $time);
    } else {
        $sec = 0;
    }

    return $time != '' ? str_replace('x', $sec, date($format, intval($usec))) : '';
}

/**
 * 间隔时间段格式化
 * @param int $time 时间戳
 * @param string $format 格式 【d：显示到天 i显示到分钟 s显示到秒】
 * @return string
 */
function time_trans($time, $format = 'd')
{
    $now = time();
    $diff = $now - $time;
    if ($diff < 60) {
        return '1分钟前';
    } else if ($diff < 3600) {
        return floor($diff / 60) . '分钟前';
    } else if ($diff < 86400) {
        return floor($diff / 3600) . '小时前';
    }
    $yes_start_time = strtotime(date('Y-m-d 00:00:00', strtotime('-1 days'))); //昨天开始时间
    $yes_end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-1 days'))); //昨天结束时间
    $two_end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-2 days'))); //2天前结束时间
    $three_end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-3 days'))); //3天前结束时间
    $four_end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-4 days'))); //4天前结束时间
    $five_end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-5 days'))); //5天前结束时间
    $six_end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-6 days'))); //6天前结束时间
    $seven_end_time = strtotime(date('Y-m-d 23:59:59', strtotime('-7 days'))); //7天前结束时间

    if ($time > $yes_start_time && $time < $yes_end_time) {
        return '昨天';
    }

    if ($time > $yes_start_time && $time < $two_end_time) {
        return '1天前';
    }

    if ($time > $yes_start_time && $time < $three_end_time) {
        return '2天前';
    }

    if ($time > $yes_start_time && $time < $four_end_time) {
        return '3天前';
    }

    if ($time > $yes_start_time && $time < $five_end_time) {
        return '4天前';
    }

    if ($time > $yes_start_time && $time < $six_end_time) {
        return '5天前';
    }

    if ($time > $yes_start_time && $time < $seven_end_time) {
        return '6天前';
    }

    switch ($format) {
        case 'd':
            $show_time = date('Y-m-d', $time);
            break;
        case 'i':
            $show_time = date('Y-m-d H:i', $time);
            break;
        case 's':
            $show_time = date('Y-m-d H:i:s', $time);
            break;
    }
    return $show_time;
}

/**
 * 根据附件表的id返回url地址
 * @param  [type] $id [description]
 */
function get_file($id)
{
    if ($id) {
        $geturl = \think\facade\Db::name("file")->where(['id' => $id])->find();
        if ($geturl['status'] == 1) {
            //审核通过
            //获取签名的URL
            $url = $geturl['filepath'];
            return $url;
        } elseif ($geturl['status'] == 0) {
            //待审核
            return '/static/webadmin/images/nonepic360x360.jpg';
        } else {
            //不通过
            return '/static/webadmin/images/nonepic360x360.jpg';
        }
    }
    return false;
}

function get_file_list($dir)
{
    $list=[];
    if(is_dir($dir)){
        $info = opendir($dir);
        while (($file = readdir($info)) !== false) {
            //echo $file.'<br>';
            $pathinfo=pathinfo($file);
            if($pathinfo['extension']=='html'){   //只获取符合后缀的文件
                array_push($list, $pathinfo);
            }
        }
        closedir($info);
    }
    return $list;
}

//获取当前登录用户的信息
function get_login_user($key = "")
{
    $session_user = get_config('app.session_user');
    if (\think\facade\Session::has($session_user)) {
        $gougu_user = \think\facade\Session::get($session_user);
        if (!empty($key)) {
            if (isset($gougu_user[$key])) {
                return $gougu_user[$key];
            } else {
                return '';
            }
        } else {
            return $gougu_user;
        }
    } else {
        return '';
    }
}

/**
 * 判断访客是否是蜘蛛
 */
function isRobot($except = '') {
    $ua = strtolower ( $_SERVER ['HTTP_USER_AGENT'] );
    $botchar = "/(baidu|google|spider|soso|yahoo|sohu-search|yodao|robozilla|AhrefsBot)/i";
    $except ? $botchar = str_replace ( $except . '|', '', $botchar ) : '';
    if (preg_match ( $botchar, $ua )) {
        return true;
    }
    return false;
}

/**
 * 客户操作日志
 * @param string $type 操作类型 login reg add edit view delete down join sign play order pay
 * @param string    $param_str 操作内容
 * @param int    $param_id 操作内容id
 * @param array  $param 提交的参数
 */
function add_user_log($type, $param_str = '', $param_id = 0, $param = [])
{
    $request = request();
    $title = '未知操作';
    $type_action = get_config('log.user_action');
    if($type_action[$type]){
        $title = $type_action[$type];
    }
    if ($type == 'login') {
        $login_user = \think\facade\Db::name('User')->where(array('id' => $param_id))->find();
        if ($login_user['nickname'] == '') {
            $login_user['nickname'] = $login_user['name'];
        }
        if ($login_user['nickname'] == '') {
            $login_user['nickname'] = $login_user['username'];
        }
    } else {
        $login_user = get_login_user();
        if (empty($login_user)) {
            $login_user = [];
            $login_user['id'] = 0;
            $login_user['nickname'] = '游客';
            if(isRobot()){
                $login_user['nickname'] = '蜘蛛';
                $type = 'spider';
                $title = '爬行';
            }
        } else {
            if ($login_user['nickname'] == '') {
                $login_user['nickname'] = $login_user['username'];
            }
        }
    }
    $content = $login_user['nickname'] . '在' . date('Y-m-d H:i:s') . '执行了' . $title . '操作';
    if ($param_str != '') {
        $content = $login_user['nickname'] . '在' . date('Y-m-d H:i:s') . $title . '了' . $param_str;
    }
    $data = [];
    $data['uid'] = $login_user['id'];
    $data['nickname'] = $login_user['nickname'];
    $data['type'] = $type;
    $data['title'] = $title;
    $data['content'] = $content;
    $data['param_id'] = $param_id;
    $data['param'] = json_encode($param);
    $data['module'] = strtolower(app('http')->getName());
    $data['controller'] = strtolower(app('request')->controller());
    $data['function'] = strtolower(app('request')->action());
    $data['ip'] = app('request')->ip();
    $data['create_time'] = time();
    \think\facade\Db::name('UserLog')->strict(false)->field(true)->insert($data);
}

/**
 * 判断是否是手机浏览器
 *  @return bool
 */
function isMobile()
{
    if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], "wap")) {
        return true;
    } elseif (isset($_SERVER['HTTP_ACCEPT']) && strpos(strtoupper($_SERVER['HTTP_ACCEPT']), "VND.WAP.WML")) {
        return true;
    } elseif (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) {
        return true;
    } elseif (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])) {
        return true;
    } else {
        return false;
    }
}


/**
 * 邮件发送
 * @param $to    接收人
 * @param string $subject 邮件标题
 * @param string $content 邮件内容(html模板渲染后的内容)
 * @throws Exception
 * @throws phpmailerException
 */
function send_email($to, $subject = '', $content = '')
{
    $mail = new PHPMailer\PHPMailer\PHPMailer();
    $email_config = \think\facade\Db::name('config')
        ->where('name', 'email')
        ->find();
    $config = unserialize($email_config['content']);

    $mail->CharSet = 'UTF-8'; //设定邮件编码，默认ISO-8859-1，如果发中文此项必须设置，否则乱码
    $mail->isSMTP();
    $mail->SMTPDebug = 0;

    //调试输出格式
    //$mail->Debugoutput = 'html';
    //smtp服务器
    $mail->Host = $config['smtp'];
    //端口 - likely to be 25, 465 or 587
    $mail->Port = $config['smtp_port'];
    if($mail->Port == '465'){
        $mail->SMTPSecure = 'ssl';// 使用安全协议
    }
    //Whether to use SMTP authentication
    $mail->SMTPAuth = true;
    //发送邮箱
    $mail->Username = $config['smtp_user'];
    //密码
    $mail->Password = $config['smtp_pwd'];
    //Set who the message is to be sent from
    $mail->setFrom($config['email'], $config['from']);
    //回复地址
    //$mail->addReplyTo('replyto@example.com', 'First Last');
    //接收邮件方
    if (is_array($to)) {
        foreach ($to as $v) {
            $mail->addAddress($v);
        }
    } else {
        $mail->addAddress($to);
    }

    $mail->isHTML(true);// send as HTML
    //标题
    $mail->Subject = $subject;
    //HTML内容转换
    $mail->msgHTML($content);
    $status = $mail->send();
    if ($status) {
        return true;
    } else {
        //  echo "Mailer Error: ".$mail->ErrorInfo;// 输出错误信息
        //  die;
        return false;
    }
}

/**
 * 验证输入的邮件地址是否合法
 * @param $user_email 邮箱
 * @return bool
 */
function is_email($user_email)
{
    $chars = "/^([a-z0-9+_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,6}\$/i";
    if (strpos($user_email, '@') !== false && strpos($user_email, '.') !== false) {
        if (preg_match($chars, $user_email)) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

/**
 * 验证输入的手机号码是否合法
 * @param $mobile_phone 手机号
 * @return bool
 */
function is_mobile_phone($mobile_phone)
{
    $chars = "/^13[0-9]{1}[0-9]{8}$|15[0-9]{1}[0-9]{8}$|18[0-9]{1}[0-9]{8}$|17[0-9]{1}[0-9]{8}$/";
    if (preg_match($chars, $mobile_phone)) {
        return true;
    }
    return false;
}


/**
 * 同步 URL 请求
 * @param string $url 请求的 URL
 * @param string $params 传递的参数
 * @param string $method 请求方式
 * @param array $header 传递的头部参数
 * @param integer $expire 超时时间
 * @param array $options CURL 参数
 * @return array|string     返回请求结果
 * @author dengwei
 * @time   2023-01-04 10:30:26
 */
function curl_sync($url, $params = '', $method = 'GET', $header = [], $expire = 30, $options = [])
{
    $cookieFile = env('runtime_path') . 'temp/' . md5(time()) . '.txt';
    $userAgent = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36';
    $ch = curl_init();
    $opt = [];
    // 请求参数
    $opt[CURLOPT_COOKIEJAR] = $cookieFile;
    $opt[CURLOPT_COOKIEFILE] = $cookieFile;
    $opt[CURLOPT_USERAGENT] = $userAgent;
    $opt[CURLOPT_CONNECTTIMEOUT] = $expire;
    $opt[CURLOPT_TIMEOUT] = $expire;
    $opt[CURLOPT_HTTPHEADER] = $header ?: ['Expect:'];
    $opt[CURLOPT_FOLLOWLOCATION] = true;
    $opt[CURLOPT_RETURNTRANSFER] = true;

    if (substr($url, 0, 8) == 'https://') {
        $opt[CURLOPT_SSL_VERIFYPEER] = false;
        $opt[CURLOPT_SSL_VERIFYHOST] = 2;
    }
    if (is_array($params)) {
        $params = http_build_query($params);
    }
    switch (strtoupper($method)) {
        case 'GET':
            $extStr = (strpos($url, '?') !== false) ? '&' : '?';
            $url = $url . (($params) ? $extStr . $params : '');
            $opt[CURLOPT_URL] = $url . '?' . $params;
            break;
        case 'POST':
            $opt[CURLOPT_POST] = true;
            $opt[CURLOPT_POSTFIELDS] = $params;
            $opt[CURLOPT_URL] = $url;
            break;
        case 'PUT':
            $opt[CURLOPT_CUSTOMREQUEST] = 'PUT';
            $opt[CURLOPT_POSTFIELDS] = $params;
            $opt[CURLOPT_URL] = $url;
            break;
        case 'DELETE':
            $opt[CURLOPT_CUSTOMREQUEST] = 'DELETE';
            $opt[CURLOPT_POSTFIELDS] = $params;
            $opt[CURLOPT_URL] = $url;
            break;
        default:
            return ['error' => 0, 'msg' => '请求的方法不存在', 'info' => []];
            break;
    }
    curl_setopt_array($ch, (array)$opt + $options);
    $result = curl_exec($ch);
    $error = curl_error($ch);
    if ($result == false || !empty($error)) {
        $errno = curl_errno($ch);
        $info = curl_getinfo($ch);
        curl_close($ch);
        return [
            'errno' => $errno,
            'msg' => $error,
            'info' => $info,
        ];
    }
    curl_close($ch);
    return $result;
}

//循环删除目录和文件函数
function delDirAndFile( $dirName='' ) {
    // opendir将目录打开，成功则返回句柄资源
    if ( $handle = opendir( "$dirName" ) ) {
        // while循环取出资源中的文件夹名称及文件名
        while ( false !== ( $item = readdir( $handle ) ) ) {
            // 过滤掉"."，".."
            if ( $item != "." && $item != ".." ) {
                // 检查当次循环是否为文件夹
                if ( is_dir( "$dirName/$item" ) ) {
                    // 递归继续打开下层目录直至文件
                    delDirAndFile( "$dirName/$item" );
                } else {
                    // 删除文件
                    if( unlink( "$dirName/$item" ) );
                }
            }
        }
        closedir( $handle ); // 释放句柄资源
        if(rmdir( $dirName )); // 删除空目录
    }

}
function deldir($path){
    //如果是目录则继续
    if(is_dir($path)){
        //扫描一个文件夹内的所有文件夹和文件并返回数组
        $p = scandir($path);
        foreach($p as $val){
            //排除目录中的.和..
            if($val !="." && $val !=".."){
                //如果是目录则递归子目录，继续操作
                if(is_dir($path.'/'.$val)){
                    //子目录中操作删除文件夹和文件
                    deldir($path.'/'.$val);
                    //目录清空后删除空文件夹
                    @rmdir($path.'/'.$val);
                }else{
                    //如果是文件直接删除
                    unlink($path.'/'.$val);
                }
            }
        }
    }
    if (is_dir_empty($path)) {
        if(rmdir( $path )); // 删除空目录
    }

}

function is_dir_empty($dir) {
    if (!is_readable($dir)) return NULL;
    return (count(scandir($dir)) == 2);
}


/**
 * 获取客户端IP(非用户服务器IP)
 * @return 客户端IP
 */
function get_ip()
{
    //获取客户端IP
    if (getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown')) {
        $ip = getenv('HTTP_CLIENT_IP');
    } elseif (getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown')) {
        $ip = getenv('HTTP_X_FORWARDED_FOR');
    } elseif (getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown')) {
        $ip = getenv('REMOTE_ADDR');
    } elseif (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown')) {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    return $ip;
}


function mlog($txt,$filename='log.txt') {
    $txt = date('Y/m/d H:i:s').": {$txt}\r\n";
    file_put_contents('./'.date('Y-m-d').$filename, $txt, FILE_APPEND); //追加内容
}
/**
 * 获取会员类型
 * @param string $value
 * @return mixed
 */
function getUserType($value)
{
    $UserType = [
        1 => '微信',
        2 => '支付宝',
        0 => '游客',
    ];
    return $UserType[$value];
}
/**
 * 获取操作类型
 * @param string $value
 * @return mixed
 */
function getBuyType($value)
{
    $buyType = [
        1 => '买入',
        2 => '卖出',
        0 => '',
    ];
    return $buyType[$value];
}

/**
 * 导出数据为excel表格
 * @param $data    一个二维数组,结构如同从数据库查出来的数组
 * @param $title   excel的第一行标题,一个数组,如果为空则没有标题
 * @param $filename 下载的文件名
 * @param exportexcel($arr,array('id','账户','密码','昵称'),'文件名!');
 */
function exportexcel($data = array(), $title = array(), $filename = 'report')
{
    header("Content-type:application/octet-stream");
    header("Accept-Ranges:bytes");
    header("Content-type:application/vnd.ms-excel");
    header("Content-Disposition:attachment;filename=" . $filename . ".xls");
    header("Pragma: no-cache");
    header("Expires: 0");
    //导出xls 开始
    if (!empty($title)) {
        foreach ($title as $k => $v) {
            $title[$k] = iconv("UTF-8", "GB2312", $v);
        }
        $title = implode("\t", $title);
        echo "$title\n";
    }
    if (!empty($data)) {
        foreach ($data as $key => $val) {
            foreach ($val as $ck => $cv) {
                $data[$key][$ck] = iconv("UTF-8", "GB2312", $cv);
            }
            $data[$key] = implode("\t", $data[$key]);
        }
        echo implode("\n", $data);
    }
}
//自定义函数或者第三方库中的函数
function excel_intercept($x, $y) {
    $n = count($x);
    $sum_x = array_sum($x);
    $sum_y = array_sum($y);
    $sum_xy = 0;
    $sum_xx = 0;

    for ($i = 0; $i < $n; $i++) {
        $sum_xy += $x[$i] * $y[$i];
        $sum_xx += $x[$i] * $x[$i];
    }

    $slope = ($n * $sum_xy - $sum_x * $sum_y) / ($n * $sum_xx - pow($sum_x, 2));
    $intercept = $sum_y / $n - $slope * $sum_x / $n;

    return $intercept;
}


function slope($x, $y) {
    $n = count($x);
    $sum_x = array_sum($x);
    $sum_y = array_sum($y);
    $sum_xy = 0;
    $sum_xx = 0;

    for ($i = 0; $i < $n; $i++) {
        $sum_xy += $x[$i] * $y[$i];
        $sum_xx += $x[$i] * $x[$i];
    }

    $slope = ($n * $sum_xy - $sum_x * $sum_y) / ($n * $sum_xx - pow($sum_x, 2));
    return $slope;
}
//计算函数的方差
function variance($arr) {
    $length = count($arr);
    if ($length == 0) {
        return array(0,0);
    }
    $average = array_sum($arr)/$length;
    $count = 0;
    foreach ($arr as $v) {
        $count += pow($average-$v, 2);
    }
    $variance = $count/$length;
    return array('variance' => $variance, 'square' => sqrt($variance), 'average' => $average);
}

// 自定义反三角函数
function inverse_trig_function($func, $value) {
    $pi = pi();
    switch ($func) {
        case 'asin':
            return asin($value) / $pi;
        case 'acos':
            return acos($value) / $pi;
        case 'atan':
            return atan($value) / $pi;
        default:
            throw new InvalidArgumentException("Invalid trigonometric function");
    }
}

function tinv($p, $mean = 0, $stdDev = 1) {
    if ($p < 0 || $p > 1) {
        return PHP_INT_MAX;
    }

    if ($stdDev <= 0) {
        return PHP_INT_MAX;
    }

    $q = sqrt(2) * erfinv(2 * $p - 1);
    $result = $mean + $q * $stdDev;

    return $result;
}
//保留几位小数，不四舍五入
function truncateDecimal($number, $digit = 2) {
    $multiplier = pow(10, $digit);
    return floor($number * $multiplier) / $multiplier;
}

//获取重复性数据第一个的平均值
function getChongfuAvg(){

    $chongfu = Db::name('Chongfu')->order('id asc')->find();
    if($chongfu){
        /*$data1=$chongfu['data1'];
        $data2=$chongfu['data2'];
        $data3=$chongfu['data3'];
        $data4=$chongfu['data4'];
        $data5=$chongfu['data5'];
        $data6=$chongfu['data6'];
        $sum=$data1+$data2+$data3+$data4+$data5+$data6;
        $avg=round($sum/6,2);*/
        return $chongfu['avgs'];
    }else{
        return 0;
    }
}

function getChongfuSds(){
    $chongfu = Db::name('Chongfu')->order('id asc')->find();
    if($chongfu){
        return $chongfu['sds'];
    }else{
        return 0;
    }
}
//SUMSQ(K4:M18)平方和的计算
function sum_pingfang($cellValues){
    // 计算平方和
    $sumSquare = 0;
    foreach ($cellValues as $value) {
        $sumSquare += $value ** 2;
    }
    return $sumSquare;
}
//计算数组元素的和
function sum_array($cellValues){
    // 计算和
    $sum = 0;
    foreach ($cellValues as $value) {
        $sum += $value;
    }
    return $sum;
}
//将二维数组转成一维数组
function flatten($arr){
    $result=array();
    foreach($arr as $value){
        if(is_array($value)){
        $result=array_merge($result,flatten($value));
        }else{
            $result[]=$value;
        }
    }
    return $result;
}
//FINV函数是Excel中的一个金融函数，用于计算一个金融工具的现值
function finv2($rate, $c1, $c2) {
    return ($c2 - $c1) / pow((1 + $rate), $c1);
}

function finv3($p, $mean = 0, $std_dev = 1) {
    if ($p < 0 || $p > 1) {
        throw new Exception('Invalid probability value');
    }

    $z = sqrt(2) * inverseErrorFunction(2 * $p - 1);
    return $mean + $std_dev * $z;
}
// 自定义函数用于计算F分布的概率密度函数
function FDist($x, $d1, $d2) {
// 根据F分布的概率密度函数公式实现计算
// 这里只是一个简单示例，具体实现可能需要更复杂的公式
    return ($d1**($d1 / 2) * $d2**($d2 / 2) * $x**($d1 / 2 - 1)) / ((($d1 * $x) + $d2)**(($d1 + $d2) / 2));
}

function finv($p, $d1, $d2) {
    $x = 0.5; // 初始值
    // 迭代次数，根据需要可以调整或增加
    $maxIterations = 100;
    $epsilon = 1e-8; // 近似解的精度
    // 迭代计算
    for ($i = 0; $i < $maxIterations; $i++) {
        $diff = $p - FDist($x, $d1, $d2);

    // 如果已经达到所需精度，返回当前值
    if (abs($diff) < $epsilon) {
        return $x;
    }
    // 更新下一次的迭代值
        $x += 0.5 * $diff;
    }
    // 在最大迭代次数内没有找到满足精度要求的解，返回null或者错误提示
    return null;
}
//保留几位小数
function sprint_data($data,$num){

    return sprintf("%.".$num."f", $data);  //输出3.14
}